/**
Copyright (c) 2008 New Gonzo <john@newgonzo.com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
**/


package com.newgonzo.cannonball.browser.rendering
{
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.events.Event;
	
	import com.newgonzo.commons.logging.Log;
	import com.newgonzo.commons.logging.ILogger;
	
	import com.newgonzo.cannonball.browser.context.IContext;
	import com.newgonzo.cannonball.browser.rendering.IRenderer;
	import com.newgonzo.cannonball.browser.rendering.IRendering;

	public class AbstractDisplayRenderer extends MovieClip implements IRenderer
	{
		protected static const log:ILogger = Log.getLogger(AbstractDisplayRenderer);
		
		private var parentRendering:IRendering;
		private var renderContext:IContext;
		private var renderContent:Object;
		
		private var preferredWidth:Number;
		private var preferredHeight:Number;
		
		private var renderContainer:Sprite;
		
		public function AbstractDisplayRenderer()
		{
			super();
		}
		
		public function set rendering(value:IRendering):void
		{
			parentRendering = value;
		}
		
		public function get rendering():IRendering
		{
			return parentRendering;
		}
		
		public function set context(value:IContext):void
		{
			log.debug(this + ".context: " + value);
			
			try
			{
				if(renderContext)
				{
					exitContext();
				}
				
				renderContext = value;
				
				if(renderContext)
				{
					enterContext();
				}
			}
			catch(e:Error)
			{
				log.error(e.toString());
			}
		}
		
		public function get context():IContext
		{
			return renderContext;
		}
		
		public function set content(value:Object):void
		{
			log.debug(this + ".content: " + value);
			
			try
			{
				if(renderContent)
				{
					unloadContent();
				}
				
				renderContent = value;
				
				if(value)
				{
					loadContent();
				}
			}
			catch(e:Error)
			{
				log.error(e.toString());
			}
		}
		
		public function get content():Object
		{
			return renderContent;
		}
		
		public function render():void
		{
		}
		
		public function destroy():void
		{
		}
		
		protected function enterContext():void
		{
			log.debug(this + ".enterContext()");
		}
		
		protected function loadContent():void
		{
			log.debug(this + ".loadContent()");
			
			container.x = paddingLeft;
			container.y = paddingTop;
			
			render();
		}
		
		protected function unloadContent():void
		{
			log.debug(this + ".unloadContent()");
		
			destroyContainer();
			container = null;
			
			destroy();
		}
		
		protected function exitContext():void
		{
			log.debug(this + ".exitContext()");
		}
		
		public function get container():Sprite
		{
			if(!renderContainer)
			{
				renderContainer = createContainer();
			}
			
			return renderContainer;
		}
		
		public function set container(value:Sprite):void
		{
			renderContainer = value;
		}
		
		public function get marginTop():Number
		{
			return getRenderedNumber("margin-top");
		}
		
		public function get marginLeft():Number
		{
			return getRenderedNumber("margin-left");
		}
		
		public function get marginRight():Number
		{
			return getRenderedNumber("margin-right");
		}
		
		public function get marginBottom():Number
		{
			return getRenderedNumber("margin-bottom");
		}
		
		public function get paddingTop():Number
		{
			return getRenderedNumber("padding-top");
		}
		
		public function get paddingLeft():Number
		{
			return getRenderedNumber("padding-left");
		}
		
		public function get paddingRight():Number
		{
			return getRenderedNumber("padding-right");
		}
		
		public function get paddingBottom():Number
		{
			return getRenderedNumber("padding-bottom");
		}
		
		public function get contentWidth():Number
		{
			return (isNaN(preferredWidth) ? super.width : preferredWidth) - (paddingLeft + paddingRight);
		}
		
		public function get contentHeight():Number
		{
			return (isNaN(preferredHeight) ? super.height : preferredHeight) - (paddingTop + paddingBottom);;
		}
		
		public function get floatLeft():Boolean
		{
			return renderContent.style.float == "left";
		}
		
		public function get floatRight():Boolean
		{
			return renderContent.style.float == "right";
		}
		
		public function get displayInline():Boolean
		{
			return renderContent.style.display == "inline";
		}
		
		override public function set width(value:Number):void
		{
			preferredWidth = value;
		}
		
		override public function set height(value:Number):void
		{
			preferredHeight = value;
		}
		
		override public function get height():Number
		{
			var renderedHeight:Number = isNaN(preferredHeight) ? super.height : preferredHeight;
			
			renderedHeight += marginTop;
			renderedHeight += paddingTop;
			renderedHeight += paddingBottom;
			renderedHeight += marginBottom;
			
			return renderedHeight;
		}
		
		override public function get width():Number
		{
			var renderedWidth:Number = isNaN(preferredWidth) ? super.width : preferredWidth;
			renderedWidth += marginLeft;
			renderedWidth += paddingLeft;
			renderedWidth += paddingRight;
			renderedWidth += marginRight;
			
			return renderedWidth;
		}
		
		protected function getRenderedNumber(style:String):Number
		{
			if(renderContent)
			{
				var value:String = renderContent.style.getPropertyValue(style);
				
				if(!value.length)
				{
					return 0;
				}
				
				return Number(value);
			}
			
			trace("NO RENDERED CONTENT!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
			return 0;
		}
		
		protected function createContainer():Sprite
		{
			return addChild(new Sprite()) as Sprite;
		}
		
		protected function destroyContainer():void
		{
			if(container.parent)
			{
				container.parent.removeChild(container);
			}
		}
	}
}
